from serial import Serial
from serial.tools import list_ports
from PyQt5.QtCore import QThread
from PyQt5.QtCore import QTimer
import PyQt5.QtWidgets as qw
from ui import ui

BAUDRATE = 115200

class SerialMessage(QThread):
    def __init__(self):
        super().__init__()
        self.serial = Serial(timeout=1)
        self.cur_port = None
        self.serial_renew = QTimer()
        self.serial_renew.timeout.connect(self._renew_port_list)
        self.serial_renew.start()
        ui.open_button.clicked.connect(self.EnevtOpen)
        ui.serial_combo.currentIndexChanged.connect(self.EventChangePort)
        self.start()

    def isOpen(self):
        return self.serial.is_open

    def EventChangePort(self, idx):
        ''' 串口或波特率改变了都会重新打开串口 '''
        if self.isOpen():
            if ui.serial_combo.currentText() != '':
                if ui.serial_combo.currentText() != self.cur_port:
                    self.Close()
                if self.cur_port in self.port_list():
                    # 串口或波特率被手动改变则重新打开, 
                    # 如果当前端口不在了, 则是设备被拔掉,不重新连接
                    self.Open()
            else:
                self.Close()

    def EnevtOpen(self):
        if self.isOpen():
            self.Close()
        else:
            self.Open()

    def Close(self):
        try:
            print("关闭串口:" + self.cur_port)
            self.serial.close()
        except:
            print("串口关闭失败")
        ui.open_button.setText("open")

    def Open(self):
        self.serial.port = ui.serial_combo.currentText()
        self.serial.baudrate = BAUDRATE
        self.cur_port = self.serial.port
        print("打开串口:" + self.cur_port)
        try:
            self.serial.open()
            ui.open_button.setText('close')
        except:
            print('串口打开失败')

    def port_list(self):
        return [i[0] for i in list(list_ports.comports())]

    def _is_port_list(self, ports):
        # 串口数量变化了就刷新
        if len(ports) != ui.serial_combo.count():
            return True
        # 有新的串口加入也刷新界面
        for p in ports:
            if ui.serial_combo.findText(p) == -1:
                return True
        return False  # 没有变化不刷新

    def _renew_port_list(self):
        ''' 在定时器中刷新串口列表 '''
        port_list = self.port_list()
        if self._is_port_list(port_list):
            ui.serial_port_signal.emit(port_list, self.cur_port)
        self.serial_renew.start(1000)

    def send(self, data):
        if not self.isOpen():
            return 0
        return self.serial.write(data)

    def recv(self):
        return self.serial.readall()

    def run(self):
        pass


serial_msg = SerialMessage()

def isOpen():
    return serial_msg.isOpen()

def send(data):
    try:
        return serial_msg.send(data)
    except:
        ui.open_button.setText("open")
        return None


def recv(size=None):
    if not serial_msg.isOpen():
        return None
    try:
        if size == None:
            return serial_msg.serial.read_all()
        else:
            return serial_msg.serial.read(size)
    except:
        ui.open_button.setText("open")
        return None
